home *** CD-ROM | disk | FTP | other *** search
/ PC World 2007 December / PCWorld_2007-12_cd.bin / v cisle / htttrack / httrack-3.41-3.exe / {app} / src / htsserver.c < prev    next >
C/C++ Source or Header  |  2006-08-15  |  54KB  |  1,675 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: Mini-server                                            */
  34. /* Author: Xavier Roche                                         */
  35. /* ------------------------------------------------------------ */
  36.  
  37.  
  38. /* specific definitions */
  39. /* specific definitions */
  40.  
  41. /* Bypass internal definition protection */
  42. #define HTS_INTERNAL_BYTECODE
  43.   #include "htsbase.h"
  44. #undef HTS_INTERNAL_BYTECODE
  45.  
  46. #include "htsnet.h"
  47. #include "htslib.h"
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <time.h>
  52. #include <fcntl.h>
  53. #ifdef _WIN32
  54. #else
  55. #include <arpa/inet.h>
  56. #endif
  57. #ifndef _WIN32
  58. #include <signal.h>
  59. #endif
  60. /* END specific definitions */
  61.  
  62. /* dΘfinitions globales */
  63. #include "htsglobal.h"
  64.  
  65. /* htslib */
  66. /*#include "htslib.h"*/
  67.  
  68. /* HTTrack Website Copier Library */
  69. #include "httrack-library.h"
  70.  
  71. /* Language files */
  72.  
  73. /* Bypass internal definition protection */
  74. #define HTS_INTERNAL_BYTECODE
  75.   #include "htsinthash.h"
  76. #undef HTS_INTERNAL_BYTECODE
  77.  
  78. int NewLangStrSz=1024;
  79. inthash NewLangStr=NULL;
  80. int NewLangStrKeysSz=1024;
  81. inthash NewLangStrKeys=NULL;
  82. int NewLangListSz=1024;
  83. inthash NewLangList=NULL;
  84. /* Language files */
  85.  
  86. #include "htsserver.h"
  87.  
  88. char* gethomedir(void);
  89. int commandRunning = 0;
  90. int commandEndRequested = 0;
  91. int commandEnd = 0;
  92. int commandReturn = 0;
  93. char* commandReturnMsg = NULL;
  94. char* commandReturnCmdl = NULL;
  95. int commandReturnSet = 0;
  96.  
  97. httrackp *global_opt = NULL;
  98.  
  99. /* Extern */
  100. extern void webhttrack_main(char* cmd);
  101. extern void webhttrack_lock(void);
  102. extern void webhttrack_release(void);
  103.  
  104. static int is_image(char* file) {
  105.   return ( (strstr(file, ".gif") != NULL) );
  106. }
  107. static int is_text(char* file) {
  108.   return ( (strstr(file, ".txt") != NULL) );
  109. }
  110. static int is_html(char* file) {
  111.   return ( (strstr(file, ".htm") != NULL) );
  112. }
  113.  
  114. static void sig_brpipe( int code ) {
  115.   /* ignore */
  116. }
  117.  
  118. static int check_readinput_t(T_SOC soc, int timeout);
  119. static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout);
  120. static int linputsoc(T_SOC soc, char* s, int max);
  121. static int check_readinput(htsblk* r);
  122. static int linputsoc_t(T_SOC soc, char* s, int max, int timeout);
  123.  
  124.  
  125. static int linput(FILE* fp,char* s,int max);
  126.  
  127.  
  128. // URL Link catcher
  129.  
  130. // 0- Init the URL catcher with standard port
  131.  
  132. // smallserver_init(&port,&return_host);
  133. T_SOC smallserver_init_std(int* port_prox, char* adr_prox, int defaultPort) {
  134.     T_SOC soc;
  135.     if (defaultPort <= 0) {
  136.         int try_to_listen_to[]={8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,
  137.             32000,32001,32002,32003,32004,32006,32006,32007,32008,32009,
  138.             42000,42001,42002,42003,42004,42006,42006,42007,42008,42009,
  139.             0,-1};
  140.         int i=0;
  141.         do {
  142.             soc=smallserver_init(&try_to_listen_to[i],adr_prox);
  143.             *port_prox=try_to_listen_to[i];
  144.             i++;
  145.         } while( (soc == INVALID_SOCKET) && (try_to_listen_to[i]>=0));
  146.     } else {
  147.         soc=smallserver_init(&defaultPort, adr_prox);
  148.         *port_prox = defaultPort;
  149.     }
  150.     return soc;
  151. }
  152.  
  153.  
  154. // 1- Init the URL catcher
  155.  
  156. // smallserver_init(&port,&return_host);
  157. T_SOC smallserver_init(int* port,char* adr) {
  158.   T_SOC soc = INVALID_SOCKET;
  159.   char h_loc[256+2];
  160.   
  161.   commandRunning = 
  162.     commandEnd = 
  163.     commandReturn = 
  164.     commandReturnSet =
  165.     commandEndRequested = 0;
  166.   if (commandReturnMsg)
  167.     free(commandReturnMsg);
  168.   commandReturnMsg = NULL;
  169.   if (commandReturnCmdl)
  170.     free(commandReturnCmdl);
  171.   commandReturnCmdl = NULL;
  172.  
  173.   if (gethostname(h_loc,256)==0) {    // host name
  174.     SOCaddr server;
  175.     int server_size=sizeof(server);
  176.     /*t_hostent* hp_loc;
  177.     t_fullhostent buffer;*/
  178.  
  179.     // effacer structure
  180.     memset(&server, 0, sizeof(server));
  181.     
  182.     /*if ( (hp_loc=vxgethostbyname(h_loc, &buffer)) )*/ {  // notre host      
  183.  
  184.       // copie adresse
  185.       // NO (bind all)
  186.       // SOCaddr_copyaddr(server, server_size, hp_loc->h_addr_list[0], hp_loc->h_length);
  187.  
  188.       SOCaddr_initany(server, server_size); 
  189.       if ( (soc = (T_SOC) socket(SOCaddr_sinfamily(server), SOCK_STREAM, 0)) != INVALID_SOCKET) {
  190.         SOCaddr_initport(server, *port);
  191.         if ( bind(soc,(struct sockaddr*) &server, server_size) == 0 ) {
  192.           /*int len;
  193.           SOCaddr server2;
  194.           len=sizeof(server2);*/
  195.           // effacer structure
  196.           /*memset(&server2, 0, sizeof(server2));
  197.           if (getsockname(soc,(struct sockaddr*) &server2,&len) == 0) {
  198.             *port=ntohs(SOCaddr_sinport(server));  // rΘcupΘrer port*/
  199.             if (listen(soc,10)>=0) {    // au pif le 10
  200.               // SOCaddr_inetntoa(adr, 128, server2, len);
  201.               strcpy(adr, h_loc);
  202.             } else {
  203. #ifdef _WIN32
  204.               closesocket(soc);
  205. #else
  206.               close(soc);
  207. #endif
  208.               soc=INVALID_SOCKET;
  209.             }
  210.             
  211.             
  212.           /*} else {
  213. #ifdef _WIN32
  214.             closesocket(soc);
  215. #else
  216.             close(soc);
  217. #endif
  218.             soc=INVALID_SOCKET;
  219.           }*/
  220.           
  221.           
  222.         } else {
  223. #ifdef _WIN32
  224.           closesocket(soc);
  225. #else
  226.           close(soc);
  227. #endif
  228.           soc=INVALID_SOCKET;
  229.         }
  230.       }
  231.     }
  232.   }
  233.   return soc;
  234. }
  235.  
  236. // 2 - Wait for URL
  237.  
  238.  
  239. // check if data is available
  240.  
  241. // smallserver
  242. // returns 0 if error
  243. // url: buffer where URL must be stored - or ip:port in case of failure
  244. // data: 32Kb
  245.  
  246. typedef struct {
  247.   char* name;
  248.   int value;
  249. } initIntElt;
  250. typedef struct {
  251.   char* name;
  252.   char* value;
  253. } initStrElt;
  254.  
  255. #define SET_ERROR(err) do { \
  256.   inthash_write(NewLangList, "error", (intptr_t)strdup(err)); \
  257.   error_redirect = "/server/error.html"; \
  258. } while(0)
  259.  
  260. int smallserver(T_SOC soc,char* url,char* method,char* data, char* path) {
  261.   int timeout=30;
  262.   int retour=0;
  263.   int willexit=0;
  264.   int buffer_size = 32768;
  265.   char* buffer = (char*)malloc(buffer_size);
  266.   String headers = STRING_EMPTY;
  267.   String output = STRING_EMPTY;
  268.   String tmpbuff = STRING_EMPTY;
  269.   String tmpbuff2 = STRING_EMPTY;
  270.   String fspath = STRING_EMPTY;
  271.     char catbuff[CATBUFF_SIZE];
  272.  
  273.   /* Load strings */
  274.   htslang_init();
  275.   if (!htslang_load(NULL, path)) {
  276.     fprintf(stderr, "unable to find lang.def and/or lang/ strings in %s\n", path);
  277.     return 0;
  278.   }
  279.   LANG_T(path, 0);
  280.  
  281.   /* Init various values */
  282.   {
  283.     char pth[1024];
  284.     char* initOn[] = { "parseall", "Cache", "ka", 
  285.       "cookies", "parsejava", "testall", "updhack", "urlhack", "index", NULL };
  286.     initIntElt initInt[] = {
  287.       { "filter", 4 },
  288.       { "travel", 2 },
  289.       { "travel2", 1 },
  290.       { "travel3", 1 },
  291.       /* */
  292.       { "connexion", 4 },
  293.       /* */
  294.       { "maxrate", 25000 },
  295.       /* */
  296.       { "build", 1 },
  297.       /* */
  298.       { "checktype", 2},
  299.       { "robots", 3 },
  300.  
  301.       { NULL, 0 } 
  302.     };
  303.     initStrElt initStr[] = {
  304.       { "user", "Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)" },
  305.       { "footer", "<!-- Mirrored from %s%s by HTTrack Website Copier/3.x [XR&CO'2006], %s -->" },
  306.       { "url2", "+*.png +*.gif +*.jpg +*.css +*.js -ad.doubleclick.net/*" },
  307.       { NULL, NULL }
  308.     };
  309.     int i = 0;
  310.     for(i = 0 ; initInt[i].name ; i++) {
  311.       char tmp[32];
  312.       sprintf(tmp, "%d", initInt[i].value);
  313.       inthash_write(NewLangList, initInt[i].name, (intptr_t)strdup(tmp));
  314.     }
  315.     for(i = 0 ; initOn[i] ; i++) {
  316.       inthash_write(NewLangList, initOn[i], (intptr_t)strdup("1"));  /* "on" */
  317.     }
  318.     for(i = 0 ; initStr[i].name ; i++) {
  319.       inthash_write(NewLangList, initStr[i].name, (intptr_t)strdup(initStr[i].value));
  320.     }
  321.     strcpybuff(pth, gethomedir());
  322.     strcatbuff(pth, "/websites");
  323.     inthash_write(NewLangList, "path", (intptr_t)strdup(pth));
  324.   }
  325.  
  326.   /* Lock */
  327.   webhttrack_lock();
  328.  
  329.   // connexion (accept)
  330.   while(!willexit && buffer != NULL && soc != INVALID_SOCKET) {
  331.     char line1[1024];
  332.     char line[8192];
  333.     char line2[1024];
  334.     T_SOC soc_c;
  335.     struct sockaddr dummyaddr;
  336.     int dummylen = sizeof(struct sockaddr);
  337.     LLint length = 0;
  338.     char* error_redirect = NULL;
  339.  
  340.     line[0] = '\0';
  341.     buffer[0] = '\0';
  342.     StringClear(headers);
  343.     StringClear(output);
  344.     StringClear(tmpbuff);
  345.     StringClear(tmpbuff2);
  346.     StringClear(fspath);
  347.     StringCat(headers, "");
  348.     StringCat(output, "");
  349.     StringCat(tmpbuff, "");
  350.     StringCat(tmpbuff2, "");
  351.     StringCat(fspath, "");
  352.     memset(&dummyaddr, 0, sizeof(dummyaddr));
  353.  
  354.     /* UnLock */
  355.     webhttrack_release();
  356.  
  357.     /* sigpipe */
  358. #ifndef _WIN32
  359.     signal( SIGPIPE , sig_brpipe );
  360. #endif
  361.  
  362.     /* Accept */
  363.     while ( (soc_c = (T_SOC) accept(soc, &dummyaddr, &dummylen)) == INVALID_SOCKET);
  364.  
  365.     /* Lock */
  366.     webhttrack_lock();
  367.  
  368.     if(linputsoc_t(soc_c, line1, sizeof(line1) - 2, timeout) > 0) {
  369.       int meth = 0;
  370.       if (strfield(line1, "get ")) {
  371.         meth = 1;
  372.       } else if (strfield(line1, "post ")) {
  373.         meth = 2;
  374.       } else if (strfield(line1, "head ")) {   /* yes, we can do that */
  375.         meth = 10;
  376.       } else {
  377. #ifdef _DEBUG
  378.         // assert(FALSE);
  379. #endif
  380.       }
  381.       if (meth) {
  382.         /* Flush headers */
  383.         length = buffer_size - 2;
  384.         while(linputsoc_t(soc_c, line, sizeof(line) - 2, timeout) > 0) {
  385.           int p;
  386.           if ((p=strfield(line,"Content-length:"))!=0) {
  387.             sscanf(line+p, LLintP, &(length));
  388.           }
  389.           else if ((p=strfield(line,"Accept-language:"))!=0) {
  390.             char tmp[32];
  391.             char* s = line + p;
  392.             /*int l;*/
  393.             while(*s == ' ') s++;
  394.             tmp[0] = '\0';
  395.             strncatbuff(tmp, s, 2);
  396.             /*l = LANG_SEARCH(path, tmp);*/
  397.           }
  398.         }
  399.         if (meth == 2) {
  400.           int sz = 0;
  401.           if (length > buffer_size - 2) {
  402.             length = buffer_size - 2;
  403.           }
  404.           if (length > 0 && (sz=recv_bl(soc_c, buffer, (int)length, timeout)) < 0) {
  405.             meth = 0;
  406.           } else {
  407.             buffer[sz] = '\0';
  408.           }
  409.         }
  410.       }
  411.  
  412.       /* Generated variables */
  413.       if (commandEnd && !commandReturnSet) {
  414.         commandReturnSet = 1;
  415.         if (commandReturn) {
  416.           char tmp[32];
  417.           sprintf(tmp, "%d", commandReturn);
  418.           inthash_write(NewLangList, "commandReturn", (intptr_t)strdup(tmp));
  419.           inthash_write(NewLangList, "commandReturnMsg", (intptr_t)commandReturnMsg);
  420.           inthash_write(NewLangList, "commandReturnCmdl", (intptr_t)commandReturnCmdl);
  421.         } else {
  422.           inthash_write(NewLangList, "commandReturn", (intptr_t)NULL);
  423.           inthash_write(NewLangList, "commandReturnMsg", (intptr_t)NULL);
  424.           inthash_write(NewLangList, "commandReturnCmdl", (intptr_t)NULL);
  425.         }
  426.       }
  427.  
  428.       /* SID check */
  429.       {
  430.         intptr_t adr = 0;
  431.         if (inthash_readptr(NewLangList, "_sid", &adr)) {
  432.           if (inthash_write(NewLangList, "sid", (intptr_t)strdup((char*)adr))) {
  433.           }
  434.         }
  435.       }
  436.  
  437.       /* check variables */
  438.       if (meth && buffer[0]) {
  439.         char* s = buffer;
  440.         char *e, *f;
  441.         strcatbuff(buffer, "&");
  442.         while( s && (e = strchr(s, '=')) && (f = strchr(s, '&')) ) {
  443.           char* ua;
  444.           int len;
  445.           String sua = STRING_EMPTY;
  446.           *e = *f = '\0';
  447.           ua = e + 1;
  448.           if (strfield2(ua, "on"))  /* hack : "on" == 1 */
  449.             ua = "1";
  450.           len = (int) strlen(ua);
  451.           unescapehttp(ua, &sua);
  452.           inthash_write(NewLangList, s, (intptr_t)StringAcquire(&sua));
  453.           s = f + 1;
  454.         }
  455.       }
  456.  
  457.  
  458.       /* Error check */
  459.       {
  460.         intptr_t adr = 0;
  461.         intptr_t adr2 = 0;
  462.         if (inthash_readptr(NewLangList, "sid", &adr)) {
  463.           if (inthash_readptr(NewLangList, "_sid", &adr2)) {
  464.             if (strcmp((char*)adr, (char*)adr2) != 0) {
  465.               meth = 0;
  466.             }
  467.           }
  468.         }
  469.       }
  470.  
  471.       /* Check variables (internal) */
  472.       if (meth) {
  473.         int doLoad=0;
  474.         intptr_t adr = 0;
  475.         if (inthash_readptr(NewLangList, "lang", &adr)) {
  476.           int n = 0;
  477.           if (sscanf((char*)adr, "%d", &n) == 1 && n > 0 && n - 1 != LANG_T(path, -1)) {
  478.             LANG_T(path, n - 1);
  479.             /* make a backup, because the GUI will override it */
  480.             inthash_write(NewLangList, "lang_", (intptr_t)strdup((char*)adr));
  481.           }
  482.         }
  483.  
  484.         /* Load existing project settings */
  485.         if (inthash_readptr(NewLangList, "loadprojname", &adr)) {
  486.           char* pname = (char*) adr;
  487.           if (*pname) {
  488.             inthash_write(NewLangList, "projname", (intptr_t)strdup(pname));
  489.           }
  490.           inthash_write(NewLangList, "loadprojname", (intptr_t)NULL);
  491.           doLoad=1;
  492.         }
  493.         else if (inthash_readptr(NewLangList, "loadprojcateg", &adr)) {
  494.           char* pname = (char*) adr;
  495.           if (*pname) {
  496.             inthash_write(NewLangList, "projcateg", (intptr_t)strdup(pname));
  497.           }
  498.           inthash_write(NewLangList, "loadprojcateg", (intptr_t)NULL);
  499.         }
  500.         
  501.         /* intial configuration */
  502.         {
  503.           if (!inthash_read(NewLangList, "conf_file_loaded", NULL)) {
  504.             inthash_write(NewLangList, "conf_file_loaded", (intptr_t)strdup("true"));
  505.             doLoad = 2;
  506.           }
  507.         }
  508.         
  509.         /* path : <path>/<project> */
  510.         if (!commandRunning) {
  511.           intptr_t adrw = 0, adrpath = 0, adrprojname = 0;
  512.           if (inthash_readptr(NewLangList, "path", &adrpath)
  513.             && inthash_readptr(NewLangList, "projname", &adrprojname)) {
  514.             StringClear(fspath);
  515.             StringCat(fspath, (char*)adrpath);
  516.             StringCat(fspath, "/");
  517.             StringCat(fspath, (char*)adrprojname);
  518.           }
  519.         }
  520.         
  521.         /* Load existing project settings */
  522.         if (doLoad) {
  523.           FILE* fp;
  524.           if (doLoad == 1) {
  525.             StringCat(fspath, "/hts-cache/winprofile.ini");
  526.           } else if (doLoad == 2) {
  527.             StringCopy(fspath, gethomedir());
  528. #ifdef _WIN32
  529.             StringCat(fspath, "/httrack.ini");
  530. #else
  531.             StringCat(fspath, "/.httrack.ini");
  532. #endif
  533.           }
  534.           fp = fopen(StringBuff(fspath), "rb");
  535.           if (fp) {
  536.             /* Read file */
  537.             while(!feof(fp)) {
  538.               char* str = line;
  539.               char* pos;
  540.               if (!linput(fp, line, sizeof(line) - 2)) {
  541.                 *str = '\0';
  542.               }
  543.               pos=strchr(line, '=');
  544.               if (pos) {
  545.                 String escline = STRING_EMPTY;
  546.                 *pos++='\0';
  547.                 if (pos[0] == '0' && pos[1] == '\0')
  548.                   *pos = '\0';   /* 0 => empty */
  549.                 unescapeini(pos, &escline);
  550.                 inthash_write(NewLangList, line, (intptr_t)StringAcquire(&escline));
  551.               }
  552.             }
  553.             
  554.             fclose(fp);
  555.           }
  556.         }
  557.         
  558.       }
  559.  
  560.       /* Execute command */
  561.       {
  562.         intptr_t adr = 0;
  563.         int p = 0;
  564.         if (inthash_readptr(NewLangList, "command", &adr)) {
  565.           if (strcmp((char*)adr, "cancel") == 0) {
  566.             if (commandRunning) {
  567.               if (!commandEndRequested) {
  568.                 commandEndRequested=1;
  569.                 hts_request_stop(global_opt, 0);
  570.               } else {
  571.                 hts_request_stop(global_opt, 1);   /* note: the force flag does not have anyeffect yet */
  572.                 commandEndRequested=2; /* will break the loop() callback */
  573.               }
  574.             }
  575.           } else if ((p=strfield((char*)adr, "cancel-file="))) {
  576.             if (commandRunning) {
  577.               hts_cancel_file_push(global_opt, (char*)adr + p);
  578.             }
  579.           } else if (strcmp((char*)adr, "cancel-parsing") == 0) {
  580.             if (commandRunning) {
  581.               hts_cancel_parsing(global_opt);
  582.             }
  583.           } else if ((p=strfield((char*)adr, "pause="))) {
  584.             if (commandRunning) {
  585.               hts_setpause(global_opt, 1);
  586.             }
  587.           } else if ((p=strfield((char*)adr, "unpause"))) {
  588.             if (commandRunning) {
  589.               hts_setpause(global_opt, 0);
  590.             }
  591.           } else if (strcmp((char*)adr, "abort") == 0) {
  592.             if (commandRunning) {
  593.               hts_request_stop(global_opt, 1);
  594.               commandEndRequested=2; /* will break the loop() callback */
  595.             }
  596.           } else if ((p=strfield((char*)adr, "add-url="))) {
  597.             if (commandRunning) {
  598.               char* ptraddr[2];
  599.               ptraddr[0] = (char*)adr + p;
  600.               ptraddr[1] = NULL;
  601.               hts_addurl(global_opt, ptraddr);
  602.             }
  603.           } else if ((p=strfield((char*)adr, "httrack"))) {
  604.             if (!commandRunning) {
  605.               intptr_t adrcd = 0;
  606.               if (inthash_readptr(NewLangList, "command_do", &adrcd)) {
  607.                 intptr_t adrw = 0, adrpath = 0, adrprojname = 0;
  608.                 if (inthash_readptr(NewLangList, "winprofile", &adrw)) {
  609.  
  610.                   /* User general profile */
  611.                   intptr_t adruserprofile = 0;
  612.                   if (inthash_readptr(NewLangList, "userprofile", &adruserprofile)
  613.                     && adruserprofile != 0) {
  614.                     int count = (int) strlen((char*)adruserprofile);
  615.                     if (count > 0) {
  616.                       FILE* fp;
  617.                       StringClear(tmpbuff);
  618.                       StringCopy(tmpbuff, gethomedir());
  619. #ifdef _WIN32
  620.                       StringCat(tmpbuff, "/httrack.ini");
  621. #else
  622.                       StringCat(tmpbuff, "/.httrack.ini");
  623. #endif
  624.                       fp = fopen(StringBuff(tmpbuff), "wb");
  625.                       if (fp != NULL) {
  626.                         (void)((int)fwrite((void*)adruserprofile, 1, count, fp));
  627.                         fclose(fp);
  628.                       }
  629.                     }
  630.                   }
  631.                   
  632.                   /* Profile */
  633.                   StringClear(tmpbuff);
  634.                   StringCat(tmpbuff, StringBuff(fspath));
  635.                   StringCat(tmpbuff, "/hts-cache/");
  636.                   
  637.                   /* Create minimal directory structure */
  638.                   if (!structcheck(StringBuff(tmpbuff))) {
  639.                     FILE* fp;
  640.                     StringCat(tmpbuff, "winprofile.ini");
  641.                     fp = fopen(StringBuff(tmpbuff), "wb");
  642.                     if (fp != NULL) {
  643.                       int count = (int) strlen((char*)adrw);
  644.                       if ((int)fwrite((void*)adrw, 1, count, fp) == count) {
  645.                         
  646.                       /* Wipe the doit.log file, useless here (all options are replicated) and
  647.                       even a bit annoying (duplicate/ghost options)
  648.                       The behaviour is exactly the same as in WinHTTrack
  649.                         */
  650.                         StringClear(tmpbuff);
  651.                         StringCat(tmpbuff, StringBuff(fspath));
  652.                         StringCat(tmpbuff, "/hts-cache/doit.log");
  653.                         remove(StringBuff(tmpbuff));
  654.                         
  655.                         /*
  656.                         RUN THE SERVER
  657.                         */
  658.                         if (strcmp((char*)adrcd, "start") == 0) {
  659.                           webhttrack_main((char*)adr + p);
  660.                         } else {
  661.                           commandRunning = 0;
  662.                           commandEnd = 1;
  663.                         }
  664.                       } else {
  665.                         char tmp[1024];
  666.                         sprintf(tmp, "Unable to write %d bytes in the the init file %s", count, StringBuff(fspath));
  667.                         SET_ERROR(tmp);
  668.                       }
  669.                       fclose(fp);
  670.                     } else {
  671.                       char tmp[1024];
  672.                       sprintf(tmp, "Unable to create the init file %s", StringBuff(fspath));
  673.                       SET_ERROR(tmp);
  674.                     }
  675.                   } else {
  676.                     char tmp[1024];
  677.                     sprintf(tmp, "Unable to create the directory structure in %s", StringBuff(fspath));
  678.                     SET_ERROR(tmp);
  679.                   }
  680.                   
  681.                 } else {
  682.                   SET_ERROR("Internal server error: unable to fetch project name or path");
  683.                 }
  684.               }
  685.             }
  686.           } else if (strcmp((char*)adr, "quit") == 0) {
  687.             willexit=1;
  688.           }
  689.           inthash_write(NewLangList, "command", (intptr_t)NULL);
  690.         }
  691.       }
  692.  
  693.       /* Response */
  694.       if (meth) {
  695.         int virtualpath = 0;
  696.         char* pos;
  697.         char* url = strchr(line1, ' ');
  698.         if (url && *++url == '/' && (pos = strchr(url, ' ')) && !(*pos = '\0') ) {
  699.           char fsfile[1024];
  700.           char* file;
  701.           FILE* fp;
  702.           char* qpos;
  703.  
  704.           /* get the URL */
  705.           if (error_redirect == NULL) {
  706.             if ( (qpos = strchr(url, '?')) ) {
  707.               *qpos = '\0';
  708.             }
  709.             fsfile[0] = '\0';
  710.             if (strcmp(url, "/") == 0) {
  711.               file = "/server/index.html";
  712.               meth = 2;
  713.             } else {
  714.               file = url;
  715.             }
  716.           } else {
  717.             file = error_redirect;
  718.             meth = 2;
  719.           }
  720.           
  721.           if (strncmp(file, "/website/", 9) == 0) {
  722.             virtualpath = 1;
  723.           }
  724.  
  725.           if (commandRunning) {
  726.             if (!is_image(file)) {
  727.               file = "/server/refresh.html";
  728.             }
  729.           } else if (commandEnd && !virtualpath && !willexit) {
  730.             if (!is_image(file)) {
  731.               file = "/server/finished.html";
  732.             }
  733.           }
  734.           
  735.           if (strlen(path) + strlen(file) + 32 < sizeof(fsfile)) {
  736.             if (strncmp(file, "/website/", 9) != 0) {
  737.               sprintf(fsfile, "%shtml%s", path, file);
  738.             } else {
  739.               intptr_t adr = 0;
  740.               if (inthash_readptr(NewLangList, "projpath", &adr)) {
  741.                 sprintf(fsfile, "%s%s", (char*)adr, file + 9);
  742.               }
  743.             }
  744.           }
  745.           
  746.           if (fsfile[0] && strstr(file, "..") == NULL && (fp = fopen(fsfile, "rb"))) {
  747.             char ok[] = "HTTP/1.0 200 OK\r\n"
  748.               "Connection: close\r\n"
  749.               "Server: httrack-small-server\r\n"
  750.               "Content-type: text/html\r\n"
  751.               "Cache-Control: no-cache, must-revalidate, private\r\n"
  752.               "Pragma: no-cache\r\n"
  753.               ;
  754.             char ok_img[] = "HTTP/1.0 200 OK\r\n"
  755.               "Connection: close\r\n"
  756.               "Server: httrack small server\r\n"
  757.               "Content-type: image/gif\r\n"
  758.               ;
  759.             char ok_text[] = "HTTP/1.0 200 OK\r\n"
  760.               "Connection: close\r\n"
  761.               "Server: httrack small server\r\n"
  762.               "Content-type: text/plain\r\n"
  763.               ;
  764.  
  765.             /* register current page */
  766.             inthash_write(NewLangList, "thisfile", (intptr_t)strdup(file));
  767.  
  768.             /* Force GET for the last request */
  769.             if (meth == 2 && willexit) {
  770.               meth = 1;
  771.             }
  772.  
  773.             /* posted data are redirected to get protocol */
  774.             if (meth == 2) {
  775.               char redir[] = "HTTP/1.0 302 Redirect\r\n"
  776.                 "Connection: close\r\n"
  777.                 "Server: httrack-small-server\r\n";
  778.               intptr_t adr = 0;
  779.               char* newfile = file;
  780.               if (inthash_readptr(NewLangList, "redirect", &adr) && adr != 0) {
  781.                 char* newadr = (char*)adr;
  782.                 if (*newadr) {
  783.                   newfile = newadr;
  784.                 }
  785.               }
  786.               StringMemcat(headers, redir, strlen(redir));
  787.               {
  788.                 char tmp[256];
  789.                 if (strlen(file) < sizeof(tmp) - 32) {
  790.                   sprintf(tmp, "Location: %s\r\n", newfile);
  791.                   StringMemcat(headers, tmp, strlen(tmp));
  792.                 }
  793.               }
  794.               inthash_write(NewLangList, "redirect", (intptr_t)NULL);
  795.             }
  796.             else if (is_html(file)) {
  797.               int outputmode = 0;
  798.               StringMemcat(headers, ok, sizeof(ok) - 1);
  799.               while(!feof(fp)) {
  800.                 char* str = line;
  801.                 int prevlen = (int) StringLength(output);
  802.                 int nocr = 0;
  803.                 if (!linput(fp, line, sizeof(line) - 2)) {
  804.                   *str = '\0';
  805.                 }
  806.                 if (*str && str[strlen(str) - 1] == '\\') {
  807.                   nocr = 1;
  808.                   str[strlen(str) - 1] = '\0';
  809.                 }
  810.                 while(*str) {
  811.                   char* pos;
  812.                   size_t n;
  813.                   if (*str == '$' && *++str == '{' && (pos = strchr(++str, '}')) && (n = (pos - str) ) && n < 1024 ) {
  814.                     char name_[1024 + 2];
  815.                     char* name = name_;
  816.                     char* langstr = NULL;
  817.                     int p;
  818.                     int format = 0;
  819.                     int listDefault = 0;
  820.                     name[0] = '\0';
  821.                     strncatbuff(name, str, n);
  822.                     if (strncmp(name, "/*", 2) == 0) {
  823.                       /* comments */
  824.                     }
  825.                     else if (( p = strfield(name, "html:"))) {
  826.                       name += p;
  827.                       format = 1;
  828.                     }
  829.                     else if (( p = strfield(name, "list:"))) {
  830.                       name += p;
  831.                       format = 2;
  832.                     }
  833.                     else if (( p = strfield(name, "liststr:"))) {
  834.                       name += p;
  835.                       format = -2;
  836.                     }
  837.                     else if (( p = strfield(name, "file-exists:"))) {
  838.                       char* pos2;
  839.                       name += p;
  840.                       format = 0;
  841.                       pos2 = strchr(name, ':');
  842.                       langstr = "";
  843.                       if (pos2 != NULL) {
  844.                         *pos2 = '\0';
  845.                         if (strstr(name, "..") == NULL) {
  846.                           if (fexist(fconcat(catbuff, path, name))) {
  847.                             langstr = pos2 + 1;
  848.                           }
  849.                         }
  850.                       }
  851.                     }
  852.                     else if (( p = strfield(name, "do:"))) {
  853.                       char* pos2;
  854.                       name += p;
  855.                       format = 1;
  856.                       pos2 = strchr(name, ':');
  857.                       langstr = "";
  858.                       if (pos2 != NULL) {
  859.                         *pos2 = '\0';
  860.                         pos2++;
  861.                       } else {
  862.                         pos2="";
  863.                       }
  864.                       if (strcmp(name, "output-mode") == 0) {
  865.                         if (strcmp(pos2, "html") == 0) {
  866.                           outputmode = 1;
  867.                         } else if (strcmp(pos2, "inifile") == 0) {
  868.                           outputmode = 2;                         
  869.                         } else if (strcmp(pos2, "html-urlescaped") == 0) {
  870.                           outputmode = 3;                         
  871.                         } else {
  872.                           outputmode = 0;
  873.                         }
  874.                       } else if (strcmp(name, "if-file-exists") == 0) {
  875.                         if (strstr(pos2, "..") == NULL) {
  876.                           if (!fexist(fconcat(catbuff, path, pos2))) {
  877.                             outputmode = -1;
  878.                           }
  879.                         }
  880.                       } else if (strcmp(name, "if-project-file-exists") == 0) {
  881.                         if (strstr(pos2, "..") == NULL) {
  882.                           if (!fexist(fconcat(catbuff, StringBuff(fspath), pos2))) {
  883.                             outputmode = -1;
  884.                           }
  885.                         }
  886.                       } else if (strcmp(name, "if-file-do-not-exists") == 0) {
  887.                         if (strstr(pos2, "..") == NULL) {
  888.                           if (fexist(fconcat(catbuff, path, pos2))) {
  889.                             outputmode = -1;
  890.                           }
  891.                         }
  892.                       } else if (strcmp(name, "if-not-empty") == 0) {
  893.                         intptr_t adr = 0;
  894.                         if (!inthash_readptr(NewLangList, pos2, &adr) || *((char*)adr) == 0 ) {
  895.                           outputmode = -1;
  896.                         }
  897.                       } else if (strcmp(name, "if-empty") == 0) {
  898.                         intptr_t adr = 0;
  899.                         if (inthash_readptr(NewLangList, pos2, &adr) && *((char*)adr) != 0 ) {
  900.                           outputmode = -1;
  901.                         }
  902.                       } else if (strcmp(name, "end-if") == 0) {
  903.                         outputmode = 0;
  904.                       } else if (strcmp(name, "loadhash") == 0) {
  905.                         intptr_t adr = 0;
  906.                         if (inthash_readptr(NewLangList, "path", &adr)) {
  907.                           char* rpath = (char*) adr;
  908.                           //find_handle h;
  909.                           if (rpath[0]) {
  910.                             if (rpath[strlen(rpath)-1]=='/') {
  911.                               rpath[strlen(rpath)-1]='\0';      /* note: patching stored (inhash) value */
  912.                             }
  913.                           }
  914.                           {
  915.                             const char* profiles = hts_getcategories(rpath, 0);
  916.                             const char* categ = hts_getcategories(rpath,1 );
  917.                             inthash_write(NewLangList, "winprofile", (intptr_t)profiles);
  918.                             inthash_write(NewLangList, "wincateg", (intptr_t)categ);
  919.                           }
  920.                         }  
  921.                       } else if (strcmp(name, "copy") == 0) {
  922.                         if (*pos2) {
  923.                           char* pos3 = strchr(pos2, ':');
  924.                           if ( pos3 && *(pos3 + 1) ) {
  925.                             intptr_t adr = 0;
  926.                             *pos3++ = '\0';
  927.                             if (inthash_readptr(NewLangList, pos2, &adr)) {
  928.                               inthash_write(NewLangList, pos3, (intptr_t)strdup((char*)adr));
  929.                               inthash_write(NewLangList, pos2, (intptr_t)NULL);
  930.                             }
  931.                           }
  932.                         }
  933.                       } else if (strcmp(name, "set") == 0) {
  934.                         if (*pos2) {
  935.                           char* pos3 = strchr(pos2, ':');
  936.                           if ( pos3 ) {
  937.                             *pos3++ = '\0';
  938.                             inthash_write(NewLangList, pos2, (intptr_t)strdup(pos3));
  939.                           } else {
  940.                             inthash_write(NewLangList, pos2, (intptr_t)NULL);
  941.                           }
  942.                         }
  943.                       }
  944.                     }
  945.                     /*
  946.                     test:<if exist>
  947.                     test:<if ==0>:<if ==1>:<if == 2>..
  948.                     ztest:<if == 0 || !exist>:<if == 1>:<if == 2>..
  949.                     */
  950.                     else if ( ( p = strfield(name, "test:")) || ( p = strfield(name, "ztest:")) ) {
  951.                       intptr_t adr = 0;
  952.                       char* pos2;
  953.                       int ztest = (name[0] == 'z');
  954.                       langstr = "";
  955.                       name += p;
  956.                       pos2 = strchr(name, ':');
  957.                       if (pos2 != NULL) {
  958.                         *pos2 = '\0';
  959.                         if (inthash_readptr(NewLangList, name, &adr) || ztest) {
  960.                           char* newadr = (char*)adr;
  961.                           if (!newadr)
  962.                             newadr = "";
  963.                           if (*newadr || ztest) {
  964.                             int npos = 0;
  965.                             name = pos2 + 1;
  966.                             format = 4;
  967.                             if (strchr(name, ':') == NULL) {
  968.                               npos = 0;  /* first is good if only one : */
  969.                               format = 0;
  970.                             } else {
  971.                               if (sscanf(newadr, "%d", &npos) != 1) {
  972.                                 if (strfield(newadr, "on")) {
  973.                                   npos = 1;
  974.                                 } else {
  975.                                   npos = 0;   /* first one will be ok */
  976.                                   format = 0;
  977.                                 }
  978.                               }
  979.                             }
  980.                             while( *name && *name != '}' && npos >= 0) {
  981.                               int end=0;
  982.                               char* fpos = strchr(name, ':');
  983.                               int n2;
  984.                               if (fpos == NULL) {
  985.                                 fpos = name + strlen(name);
  986.                                 end=1;
  987.                               }
  988.                               n2 = (int) (fpos - name);
  989.                               if (npos == 0) {
  990.                                 langstr = name;
  991.                                 *fpos='\0';
  992.                               } else if (end) {
  993.                                 npos=0;
  994.                               }
  995.                               name += n2 + 1;
  996.                               npos--;
  997.                             }
  998.                           }
  999.                         }
  1000.                       }
  1001.                     }
  1002.                     else if (( p = strfield(name, "listid:"))) {
  1003.                       char* pos2;
  1004.                       name += p;
  1005.                       format = 2;
  1006.                       pos2 = strchr(name, ':');
  1007.                       if (pos2) {
  1008.                         char dname[32];
  1009.                         int n2 = (int) (pos2 - name);
  1010.                         if (n2 > 0 && n2 < sizeof(dname) - 2) {
  1011.                           intptr_t adr = 0;
  1012.                           dname[0] = '\0';
  1013.                           strncatbuff(dname, name, n2);
  1014.                           if (inthash_readptr(NewLangList, dname, &adr)) {
  1015.                             int n = 0;
  1016.                             if (sscanf((char*)adr, "%d", &n) == 1) {
  1017.                               listDefault = n;
  1018.                             }
  1019.                           }
  1020.                           name += n2 + 1;
  1021.                         }
  1022.                       }
  1023.                     }
  1024.                     else if (( p = strfield(name, "checked:"))) {
  1025.                       name += p;
  1026.                       format = 3;
  1027.                     }
  1028.                     if (langstr == NULL) {
  1029.                       if (strfield2(name, "#iso")) {
  1030.                         langstr = line2;
  1031.                         langstr[0] = '\0';
  1032.                         LANG_LIST(path, langstr);
  1033.                         assertf(strlen(langstr) < sizeof(line2) - 2);
  1034.                       } else {
  1035.                         langstr = LANGSEL(name);
  1036.                         if (langstr == NULL || *langstr == '\0') {
  1037.                           intptr_t adr = 0;
  1038.                           if (inthash_readptr(NewLangList, name, &adr)) {
  1039.                             char* newadr = (char*)adr;
  1040.                             langstr = newadr;
  1041.                           }
  1042.                         }
  1043.                       }
  1044.                     }
  1045.                     if (langstr && outputmode != -1) {
  1046.                       switch(format) {
  1047.                       case 0:
  1048.                         {
  1049.                           char* a = langstr;
  1050.                           while(*a) {
  1051.                             if (a[0] == '\\' && isxdigit(a[1]) && isxdigit(a[2])) {
  1052.                               int n;
  1053.                               char c;
  1054.                               if (sscanf(a+1, "%x", &n) == 1) {
  1055.                                 c = (char)n;
  1056.                                 StringMemcat(output, &c, 1);
  1057.                               }
  1058.                               a += 2;
  1059.                             } else if (outputmode && a[0] == '<') {
  1060.                               StringCat(output, "<");
  1061.                             } else if (outputmode && a[0] == '>') {
  1062.                               StringCat(output, ">");
  1063.                             } else if (outputmode && a[0] == '&') {
  1064.                               StringCat(output, "&");
  1065.                             } else if (outputmode == 3 && a[0] == ' ') {
  1066.                               StringCat(output, "%20");
  1067.                             } else if (outputmode >= 2 && ((unsigned char)a[0]) < 32) {
  1068.                               char tmp[32];
  1069.                               sprintf(tmp, "%%%02x", (unsigned char)a[0]);
  1070.                               StringCat(output, tmp);
  1071.                             } else if (outputmode == 2 && a[0] == '%') {
  1072.                               StringCat(output, "%%");
  1073.                             } else if (outputmode == 3 && a[0] == '%') {
  1074.                               StringCat(output, "%25");
  1075.                             } else {
  1076.                               StringMemcat(output, a, 1);
  1077.                             }
  1078.                             a++;
  1079.                           }
  1080.                         }
  1081.                         break;
  1082.                       case 3:
  1083.                         if (*langstr) {
  1084.                           StringCat(output, "checked");
  1085.                         }
  1086.                         break;
  1087.                       default: 
  1088.                         if (*langstr) {
  1089.                           int id=1;
  1090.                           char* fstr = langstr;
  1091.                           StringClear(tmpbuff);
  1092.                           if (format == 2) {
  1093.                             StringCat(output, "<option value=1>");
  1094.                           } else if (format == -2) {
  1095.                             StringCat(output, "<option value=\"");
  1096.                           }
  1097.                           while(*fstr) {
  1098.                             switch(*fstr) {
  1099.                             case 13: break;
  1100.                             case 10:
  1101.                               if (format == 1) {
  1102.                                 StringCat(output, StringBuff(tmpbuff));
  1103.                                 StringCat(output, "<br>\r\n");
  1104.                               } else if (format == -2) {
  1105.                                 StringCat(output, StringBuff(tmpbuff));
  1106.                                 StringCat(output, "\">");
  1107.                                 StringCat(output, StringBuff(tmpbuff));
  1108.                                 StringCat(output, "</option>\r\n");
  1109.                                 StringCat(output, "<option value=\"");
  1110.                               } else {
  1111.                                 char tmp[32];
  1112.                                 sprintf(tmp, "%d", ++id);
  1113.                                 StringCat(output, StringBuff(tmpbuff));
  1114.                                 StringCat(output, "</option>\r\n");
  1115.                                 StringCat(output, "<option value=");
  1116.                                 StringCat(output, tmp);
  1117.                                 if (listDefault == id) {
  1118.                                   StringCat(output, " selected");
  1119.                                 }
  1120.                                 StringCat(output, ">");
  1121.                               }
  1122.                               StringClear(tmpbuff);
  1123.                               break;
  1124.                             case '<':
  1125.                               StringCat(tmpbuff, "<");
  1126.                               break;
  1127.                             case '>':
  1128.                               StringCat(tmpbuff, ">");
  1129.                               break;
  1130.                             case '&':
  1131.                               StringCat(tmpbuff, "&");
  1132.                               break;
  1133.                             default:
  1134.                               StringMemcat(tmpbuff, fstr, 1);
  1135.                               break;
  1136.                             }
  1137.                             fstr++;
  1138.                           }
  1139.                           if (format == 2) {
  1140.                             StringCat(output, StringBuff(tmpbuff));
  1141.                             StringCat(output, "</option>");
  1142.                           } else if (format == -2) {
  1143.                             StringCat(output, StringBuff(tmpbuff));
  1144.                             StringCat(output, "\">");
  1145.                             StringCat(output, StringBuff(tmpbuff));
  1146.                             StringCat(output, "</option>");
  1147.                           } else {
  1148.                             StringCat(output, StringBuff(tmpbuff));
  1149.                           }
  1150.                           StringClear(tmpbuff);
  1151.                         }
  1152.                       }
  1153.                     }
  1154.                     str = pos;
  1155.                   } else {
  1156.                     if (outputmode != -1) {
  1157.                       StringMemcat(output, str, 1);
  1158.                     }
  1159.                   }
  1160.                   str++;
  1161.                 }
  1162.                 if (!nocr && prevlen != StringLength(output)) {
  1163.                   StringCat(output, "\r\n");
  1164.                 }
  1165.               }
  1166. #ifdef _DEBUG
  1167.               {
  1168.                 int len = (int)strlen((char*)StringBuff(output));
  1169.                 assert(len == (int)StringLength(output));
  1170.               }
  1171. #endif
  1172.             } else if (is_text(file)) {
  1173.               StringMemcat(headers, ok_text, sizeof(ok_text) - 1);
  1174.               while(!feof(fp)) {
  1175.                 int n = (int) fread(line, 1, sizeof(line) - 2, fp);
  1176.                 if (n > 0) {
  1177.                   StringMemcat(output, line, n);
  1178.                 }
  1179.               }
  1180.             } else {
  1181.               StringMemcat(headers, ok_img, sizeof(ok_img) - 1);
  1182.               while(!feof(fp)) {
  1183.                 int n = (int) fread(line, 1, sizeof(line) - 2, fp);
  1184.                 if (n > 0) {
  1185.                   StringMemcat(output, line, n);
  1186.                 }
  1187.               }
  1188.             }
  1189.             fclose(fp);
  1190.           } else {
  1191.             char error_hdr[] = "HTTP/1.0 404 Not Found\r\n"
  1192.               "Server: httrack small server\r\n"
  1193.               "Content-type: text/html\r\n";
  1194.             char error[] = 
  1195.               "Page not found.\r\n";
  1196.             StringCat(headers, error_hdr);
  1197.             StringCat(output, error);
  1198.             //assert(file == NULL);
  1199.           }
  1200.         }
  1201.       } else {
  1202. #ifdef _DEBUG
  1203.         char error_hdr[] = "HTTP/1.0 500 Server Error\r\n"
  1204.           "Server: httrack small server\r\n"
  1205.           "Content-type: text/html\r\n";
  1206.         char error[] = 
  1207.           "Server error.\r\n";
  1208.         StringCat(headers, error_hdr);
  1209.         StringCat(output, error);
  1210. #endif
  1211.       }
  1212.       {
  1213.         char tmp[256];
  1214.         sprintf(tmp, "Content-length: %d\r\n", (int) StringLength(output));
  1215.         StringCat(headers, tmp);
  1216.       }
  1217.       StringCat(headers, "\r\n");
  1218.       if (
  1219.           (send(soc_c, StringBuff(headers), (int) StringLength(headers), 0) != StringLength(headers))
  1220.           ||
  1221.           ( (meth == 1) && (send(soc_c, StringBuff(output), (int) StringLength(output), 0) != StringLength(output)) )
  1222.         ) {
  1223. #ifdef _DEBUG
  1224.         //assert(FALSE);
  1225. #endif
  1226.       }
  1227.     } else {
  1228. #ifdef _DEBUG
  1229.       // assert(FALSE);
  1230. #endif
  1231.     }
  1232.     
  1233.     /* Shutdown (FIN) and wait until confirmed */
  1234.     {
  1235.       char c;
  1236. #ifdef _WIN32
  1237.       shutdown(soc_c, SD_SEND);
  1238. #else
  1239.       shutdown(soc_c, 1);
  1240. #endif
  1241.       /* This is necessary as IE sometimes (!) sends an additional CRLF after POST data */
  1242.       while(recv(soc_c, ((char*)&c), 1, 0) > 0);
  1243.     }
  1244.  
  1245. #ifdef _WIN32
  1246.     closesocket(soc_c);
  1247. #else
  1248.     close(soc_c);
  1249. #endif
  1250.   }
  1251.  
  1252.   if (soc != INVALID_SOCKET) {
  1253. #ifdef _WIN32
  1254.     closesocket(soc);
  1255. #else
  1256.     close(soc);
  1257. #endif
  1258.   }
  1259.  
  1260.   StringFree(headers);
  1261.   StringFree(output);
  1262.   StringFree(tmpbuff);
  1263.   StringFree(tmpbuff2);
  1264.   StringFree(fspath);
  1265.  
  1266.   if (buffer)
  1267.     free(buffer);
  1268.  
  1269.   if (commandReturnMsg)
  1270.     free(commandReturnMsg);
  1271.   commandReturnMsg = NULL;
  1272.   if (commandReturnCmdl)
  1273.     free(commandReturnCmdl);
  1274.   commandReturnCmdl = NULL;
  1275.  
  1276.   /* Unlock */
  1277.   webhttrack_release();
  1278.  
  1279.   return retour;
  1280. }
  1281.  
  1282.  
  1283.  
  1284. /* Language files */
  1285.  
  1286.  
  1287. int htslang_init(void) {
  1288.   if (NewLangList==NULL) {
  1289.     int i = 0;
  1290.     NewLangList=inthash_new(NewLangListSz);
  1291.     if (NewLangList==NULL) {
  1292.       abortLog("Error in lang.h: not enough memory");
  1293.     } else {
  1294.       inthash_value_is_malloc(NewLangList,1);
  1295.     }
  1296.   }
  1297.   return 1;
  1298. }
  1299.  
  1300. int htslang_uninit(void) {
  1301.   if (NewLangList!=NULL) {
  1302.     inthash_delete(&NewLangList);
  1303.   }
  1304.   return 1;
  1305. }
  1306.  
  1307. int smallserver_setkey(char* key, char* value) {
  1308.   return inthash_write(NewLangList, key, (intptr_t)strdup(value));
  1309. }
  1310. int smallserver_setkeyint(char* key, LLint value) {
  1311.   char tmp[256];
  1312.   sprintf(tmp, LLintP, value);
  1313.   return inthash_write(NewLangList, key, (intptr_t)strdup(tmp));
  1314. }
  1315. int smallserver_setkeyarr(char* key, int id, char* key2, char* value) {
  1316.   char tmp[256];
  1317.   sprintf(tmp, "%s%d%s", key, id, key2);
  1318.   return inthash_write(NewLangList, tmp, (intptr_t)strdup(value));
  1319. }
  1320.  
  1321. static int htslang_load(char* limit_to, char* path) {
  1322.   char* hashname;
  1323.     char catbuff[CATBUFF_SIZE];
  1324.   //
  1325.   int selected_lang=LANG_T(path, -1);
  1326.   //
  1327.   if (!limit_to) {
  1328.     LANG_DELETE();
  1329.     NewLangStr=inthash_new(NewLangStrSz);
  1330.     NewLangStrKeys=inthash_new(NewLangStrKeysSz);
  1331.     if ((NewLangStr==NULL) || (NewLangStrKeys==NULL)) {
  1332.       abortLog("Error in lang.h: not enough memory");
  1333.     } else {
  1334.       inthash_value_is_malloc(NewLangStr,1);
  1335.       inthash_value_is_malloc(NewLangStrKeys,1);
  1336.     }
  1337.   }
  1338.  
  1339.   /* Load master file (list of keys and internal keys) */
  1340.   if (!limit_to) {
  1341.     char* mname = "lang.def";
  1342.     FILE* fp=fopen(fconcat(catbuff, path, mname),"rb");
  1343.     if (fp) {
  1344.       char intkey[8192];
  1345.       char key[8192];
  1346.       while(!feof(fp)) {
  1347.         linput_cpp(fp,intkey,8000);
  1348.         linput_cpp(fp,key,8000);
  1349.         if (strnotempty(intkey) && strnotempty(key)) {
  1350.           char* test=LANGINTKEY(key);
  1351.  
  1352.           /* Increment for multiple definitions */
  1353.           if (strnotempty(test)) {
  1354.             int increment=0;
  1355.             size_t pos = strlen(key);
  1356.             do {
  1357.               increment++;
  1358.               sprintf(key+pos,"%d",increment);
  1359.               test=LANGINTKEY(key);
  1360.             }  while (strnotempty(test));
  1361.           }
  1362.  
  1363.           if (!strnotempty(test)) {         // Θviter doublons
  1364.             // conv_printf(key,key);
  1365.             int len;
  1366.             char* buff;
  1367.             len = (int) strlen(intkey);
  1368.             buff=(char*)malloc(len+2);
  1369.             if (buff) {
  1370.               strcpybuff(buff,intkey);
  1371.               inthash_add(NewLangStrKeys,key,(intptr_t)buff);
  1372.             }
  1373.           }
  1374.         } // if
  1375.       }  // while
  1376.       fclose(fp);
  1377.     } else {
  1378.       return 0;
  1379.     }
  1380.   }
  1381.   
  1382.   /* Language Name? */
  1383.   {
  1384.     char name[256];
  1385.     sprintf(name,"LANGUAGE_%d",selected_lang+1);
  1386.     hashname=LANGINTKEY(name);
  1387.   }
  1388.  
  1389.   /* Get only language name */
  1390.   if (limit_to) {
  1391.     if (hashname)
  1392.       strcpybuff(limit_to, hashname);
  1393.     else
  1394.       strcpybuff(limit_to, "???");
  1395.     return 0;
  1396.   }
  1397.  
  1398.   /* Error */
  1399.   if (!hashname)
  1400.     return 0;
  1401.  
  1402.   /* Load specific language file */
  1403.   {
  1404.     int loops;
  1405.     // 2nd loop: load undefined strings
  1406.     for(loops=0;loops<2;loops++) {
  1407.       FILE* fp;
  1408.       char lbasename[1024];
  1409.       {
  1410.         char name[256];
  1411.         sprintf(name,"LANGUAGE_%d",(loops==0)?(selected_lang+1):1);
  1412.         hashname=LANGINTKEY(name);
  1413.       }
  1414.       sprintf(lbasename, "lang/%s.txt",hashname);
  1415.       fp=fopen(fconcat(catbuff, path, lbasename), "rb");
  1416.       if (fp) {
  1417.         char extkey[8192];
  1418.         char value[8192];
  1419.         while(!feof(fp)) {
  1420.           linput_cpp(fp,extkey,8000);
  1421.           linput_cpp(fp,value,8000);
  1422.           if (strnotempty(extkey) && strnotempty(value)) {
  1423.             int len;
  1424.             char* buff;
  1425.             char* intkey;
  1426.             
  1427.             intkey=LANGINTKEY(extkey);
  1428.             
  1429.             if (strnotempty(intkey)) {
  1430.               
  1431.               /* Increment for multiple definitions */
  1432.               {
  1433.                 char* test=LANGSEL(intkey);
  1434.                 if (strnotempty(test)) {
  1435.                   if (loops == 0) {
  1436.                     int increment=0;
  1437.                     size_t pos=strlen(extkey);
  1438.                     do {
  1439.                       increment++;
  1440.                       sprintf(extkey+pos,"%d",increment);
  1441.                       intkey=LANGINTKEY(extkey);
  1442.                       if (strnotempty(intkey))
  1443.                         test=LANGSEL(intkey);
  1444.                       else
  1445.                         test="";
  1446.                     }  while (strnotempty(test));
  1447.                   } else
  1448.                     intkey="";
  1449.                 } else {
  1450.                   if (loops > 0) {
  1451.                     //err_msg += intkey;
  1452.                     //err_msg += " ";
  1453.                   }
  1454.                 }
  1455.               }
  1456.               
  1457.               /* Add key */
  1458.               if (strnotempty(intkey)) {
  1459.                 len = (int) strlen(value);
  1460.                 buff=(char*)malloc(len+2);
  1461.                 if (buff) {
  1462.                   conv_printf(value,buff);
  1463.                   inthash_add(NewLangStr,intkey,(intptr_t)buff);
  1464.                 }
  1465.               }
  1466.               
  1467.             }
  1468.           } // if
  1469.         }  // while
  1470.         fclose(fp);
  1471.       } else {
  1472.         return 0;
  1473.       }
  1474.     }
  1475.   }
  1476.  
  1477.   // Control limit_to
  1478.   if (limit_to)
  1479.     limit_to[0]='\0';
  1480.  
  1481.   return 1;
  1482. }
  1483.  
  1484. /* NOTE : also contains the "webhttrack" hack */
  1485. static void conv_printf(char* from,char* to) {
  1486.   int i=0,j=0,len;
  1487.   len = (int) strlen(from);
  1488.   while(i<len) {
  1489.     switch(from[i]) {
  1490.     case '\\': 
  1491.       i++;
  1492.       switch(from[i]) {
  1493.       case 'a': to[j]='\a'; break;
  1494.       case 'b': to[j]='\b'; break;
  1495.       case 'f': to[j]='\f'; break;
  1496.       case 'n': to[j]='\n'; break;
  1497.       case 'r': to[j]='\r'; break;
  1498.       case 't': to[j]='\t'; break;
  1499.       case 'v': to[j]='\v'; break;
  1500.       case '\'': to[j]='\''; break;
  1501.       case '\"': to[j]='\"'; break;
  1502.       case '\\': to[j]='\\'; break;
  1503.       case '?': to[j]='\?'; break;
  1504.       default: to[j]=from[i]; break;
  1505.       }
  1506.       break;
  1507.       default: 
  1508.         to[j]=from[i]; 
  1509.         break;
  1510.     }
  1511.     i++;
  1512.     j++;
  1513.   }
  1514.   to[j++]='\0';
  1515.   /* Dirty hack */
  1516.   {
  1517.     char * a = to;
  1518.     while((a = strstr(a, "WinHTTrack"))) {
  1519.       a[0] = 'W';
  1520.       a[1] = 'e';
  1521.       a[2] = 'b';
  1522.       a++;
  1523.     }
  1524.   }
  1525. }
  1526.  
  1527. static void LANG_DELETE(void) {
  1528.   inthash_delete(&NewLangStr);
  1529.   inthash_delete(&NewLangStrKeys);
  1530. }
  1531.  
  1532. // sΘlection de la langue
  1533. static void LANG_INIT(char* path) {
  1534.   //CWinApp* pApp = AfxGetApp();
  1535.   //if (pApp) {
  1536.     int test = 0; /* pApp->GetProfileInt("Language","IntId",0); */
  1537.     LANG_T(path, 0 /*pApp->GetProfileInt("Language","IntId",0)*/ );
  1538.   //}
  1539. }
  1540.  
  1541. static int LANG_T(char* path, int l) {
  1542.   if (l>=0) {
  1543.     QLANG_T(l);
  1544.     htslang_load(NULL, path);
  1545.   }
  1546.   return QLANG_T(-1);  // 0=default (english)
  1547. }
  1548.  
  1549. static int LANG_SEARCH(char* path, char* iso) {
  1550.   char lang_str[1024];
  1551.   int i = 0;
  1552.   int curr_lng=LANG_T(path, -1);
  1553.   int found = 0;
  1554.   do {
  1555.     QLANG_T(i);
  1556.     strcpybuff(lang_str,"LANGUAGE_ISO");
  1557.     htslang_load(lang_str, path);
  1558.     if (strfield(iso, lang_str)) {
  1559.       found = i;
  1560.     }
  1561.     i++;
  1562.   } while(strlen(lang_str) > 0);
  1563.   QLANG_T(curr_lng);
  1564.   return found;
  1565. }
  1566.  
  1567. static int LANG_LIST(char* path, char* buffer) {
  1568.   char lang_str[1024];
  1569.   int i = 0;
  1570.   int curr_lng=LANG_T(path, -1);
  1571.   int found = 0;
  1572.   buffer[0] = '\0';
  1573.   do {
  1574.     QLANG_T(i);
  1575.     strcpybuff(lang_str, "LANGUAGE_NAME");
  1576.     htslang_load(lang_str, path);
  1577.     if (strlen(lang_str) > 0) {
  1578.       if (buffer[0])
  1579.         strcatbuff(buffer, "\n");
  1580.       strcatbuff(buffer, lang_str);
  1581.     }
  1582.     i++;
  1583.   } while(strlen(lang_str) > 0);
  1584.   QLANG_T(curr_lng);
  1585.   return i;
  1586. }
  1587.  
  1588. static int QLANG_T(int l) {
  1589.   static int lng=0;
  1590.   if (l>=0) {
  1591.     lng=l;
  1592.   }
  1593.   return lng;  // 0=default (english)
  1594. }
  1595.  
  1596. static char* LANGSEL(char* name) {
  1597.   intptr_t adr = 0;
  1598.   if (NewLangStr)
  1599.   if (!inthash_read(NewLangStr,name,&adr))
  1600.     adr=0;
  1601.   if (adr) {
  1602.     return (char*)adr;
  1603.   }
  1604.   return "";
  1605. }
  1606.  
  1607. static char* LANGINTKEY(char* name) {
  1608.   intptr_t adr=0;
  1609.   if (NewLangStrKeys)
  1610.   if (!inthash_read(NewLangStrKeys,name,&adr))
  1611.     adr=0;
  1612.   if (adr) {
  1613.     return (char*)adr;
  1614.   }
  1615.   return "";
  1616. }
  1617.  
  1618.  
  1619.  
  1620.  
  1621. /* *** Various functions *** */
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627. static int recv_bl(T_SOC soc, void* buffer, size_t len, int timeout) {
  1628.   if (check_readinput_t(soc, timeout)) {
  1629.     int n = 1;
  1630.     size_t size = len;
  1631.     size_t offs = 0;
  1632.     while(n > 0 && size > 0) {
  1633.       n = recv(soc, ((char*)buffer) + offs, (int) size, 0);
  1634.       if (n > 0) {
  1635.         offs += n;
  1636.         size -= n;
  1637.       }
  1638.     }
  1639.     return (int)offs;
  1640.   }
  1641.   return -1;
  1642. }
  1643.  
  1644.  
  1645. // check if data is available
  1646. static int check_readinput(htsblk* r) {
  1647.   if (r->soc != INVALID_SOCKET) {
  1648.     fd_set fds;           // poll structures
  1649.     struct timeval tv;          // structure for select
  1650.     FD_ZERO(&fds);
  1651.     FD_SET(r->soc,&fds);           
  1652.     tv.tv_sec=0;
  1653.     tv.tv_usec=0;
  1654.     select(r->soc + 1,&fds,NULL,NULL,&tv);
  1655.     if (FD_ISSET(r->soc,&fds))
  1656.       return 1;
  1657.     else
  1658.       return 0;
  1659.   } else
  1660.     return 0;
  1661. }
  1662.  
  1663.  
  1664. /*int strfield(const char* f,const char* s) {
  1665.   int r=0;
  1666.   while (streql(*f,*s) && ((*f)!=0) && ((*s)!=0)) { f++; s++; r++; }
  1667.   if (*s==0)
  1668.     return r;
  1669.   else
  1670.     return 0;
  1671. }*/
  1672.  
  1673. /* same, except + */
  1674.  
  1675.